#include "espWifiCfg.h"

EspWifiCfg::EspWifiCfg(const char* apSsid, const char* apPassword) : _apSsid(apSsid), _apPassword(apPassword), _server(80) {}

void EspWifiCfg::begin() {
    WiFi.mode(WIFI_AP);
    WiFi.softAP(_apSsid, _apPassword);

    // 启动 DNS 服务器，用于 Captive Portal
    _dnsServer.start(53, "*", WiFi.softAPIP());

    // 路由
    _server.on("/", std::bind(&EspWifiCfg::_handleRoot, this));
    _server.on("/wifilist", std::bind(&EspWifiCfg::_handleWifiList, this));
    _server.on("/connect", std::bind(&EspWifiCfg::_handleConnect, this));
    _server.onNotFound(std::bind(&EspWifiCfg::_handleNotFound, this));

    _server.begin();
    Serial.printf("AP started, SSID: %s, IP: %s\n", _apSsid, WiFi.softAPIP().toString().c_str());
}

void EspWifiCfg::loop() {
    _dnsServer.processNextRequest();
    _server.handleClient();
}

void EspWifiCfg::_handleRoot() {
    String html = R"rawliteral(
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>ESP32 WiFi 配网</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    body { background-color:#f8f9fa; }
    .container { margin-top: 40px; max-width: 400px; }
    .card { border-radius: 12px; box-shadow:0 4px 10px rgba(0,0,0,0.1); }
    #title { font-size: 1.6rem; font-weight: 600; text-align: center; margin-bottom: 20px; }
    .ssid-item { 
      cursor: pointer; 
      font-size: 1.2rem; 
      text-decoration: underline; 
      padding: 12px; 
    }
    .ssid-item:hover { background-color:#e9ecef; }
    .btn-refresh { 
      height: 48px; 
      padding: 0 25px; 
      margin-top: 20px; 
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    #wifiPage, #pwdPage { display:none; }
    .wifi-name { font-size: 1.3rem; font-weight: 600; text-align: center; margin-bottom: 15px; }
    /* 密码页改进样式 */
    #pwdTitle { font-size: 1.6rem; font-weight: 700; text-align: center; margin-bottom: 20px; }
    #pwd { 
      display: block; 
      margin: 0 auto 25px auto; 
      width: 80%; 
      height: 50px; 
      font-size: 1.2rem; 
      text-align: center;
    }
    .btn-row {
      display: flex;
      justify-content: center;
      gap: 15px;
    }
    .btn-row button {
      min-width: 100px;
      height: 45px;
    }
  </style>
</head>
<body>
<div class="container">
  <div class="card">
    <div class="card-body d-flex flex-column" style="min-height:400px">

      <!-- WiFi列表页 -->
      <div id="wifiPage" class="d-flex flex-column flex-grow-1">
        <div id="title">搜索网络，请等待...</div>
        <ul class="list-group flex-grow-1" id="wifiList"></ul>
        <button class="btn btn-primary btn-refresh" onclick="loadWifiList()">刷新</button>
      </div>

      <!-- 密码输入页 -->
      <div id="pwdPage">
        <div id="pwdTitle">输入WiFi密码</div>
        <div class="wifi-name" id="ssidText"></div>
        <form onsubmit="event.preventDefault(); connectWifi();">
          <input type="password" class="form-control" id="pwd" placeholder="请输入密码">
          <div class="btn-row">
            <button type="submit" class="btn btn-success">连接</button>
            <button type="button" class="btn btn-secondary" onclick="backToWifiList()">返回</button>
          </div>
        </form>
      </div>

    </div>
  </div>
</div>

<script>
let selectedSsid = '';

function showPage(page){
  document.getElementById('wifiPage').style.display = (page==='wifi')?'block':'none';
  document.getElementById('pwdPage').style.display  = (page==='pwd')?'block':'none';
}

function loadWifiList(){
  document.getElementById('title').innerText = "搜索网络，请等待...";
  document.getElementById('wifiList').innerHTML = "";

  fetch('/wifilist').then(r=>r.json()).then(list=>{
    let html='';
    list.forEach(w=>{
      html += `<li class="list-group-item ssid-item" onclick="selectWifi('${w.ssid}')">${w.ssid}</li>`;
    });
    document.getElementById('wifiList').innerHTML = html;
    document.getElementById('title').innerText = "选择WiFi网络";
  });
}

function selectWifi(ssid){
  selectedSsid = ssid;
  document.getElementById('ssidText').innerText = ssid;
  document.getElementById('pwd').value = '';
  showPage('pwd');
}

function backToWifiList(){
  showPage('wifi');
  loadWifiList();
}

function connectWifi(){
  let pwd = document.getElementById('pwd').value;
  fetch(`/connect?ssid=${encodeURIComponent(selectedSsid)}&pwd=${encodeURIComponent(pwd)}`)
    .then(r=>r.text())
    .then(msg=>{
      alert(msg);
      showPage('wifi');
      loadWifiList();
    });
}

showPage('wifi');
loadWifiList();
</script>
</body>
</html>
)rawliteral";
    _server.send(200, "text/html", html);
}

void EspWifiCfg::_handleWifiList() {
    int n = WiFi.scanNetworks();
    String json = "[";
    for (int i = 0; i < n; i++) {
        if (i > 0) json += ",";
        json += "{\"ssid\":\"" + WiFi.SSID(i) + "\",\"rssi\":" + String(WiFi.RSSI(i)) + "}";
    }
    json += "]";
    _server.send(200, "application/json", json);
}

void EspWifiCfg::_handleConnect() {
    String ssid = _server.arg("ssid");
    String pwd = _server.arg("pwd");

    if (ssid.isEmpty()) {
        _server.send(400, "text/plain", "缺少SSID参数");
        return;
    }

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid.c_str(), pwd.c_str());

    unsigned long start = millis();
    while (WiFi.status() != WL_CONNECTED && millis() - start < 10000) {
        delay(500);
        Serial.print(".");
    }
    if (WiFi.status() == WL_CONNECTED) {
        _server.send(200, "text/plain", "WiFi连接成功: " + WiFi.localIP().toString());
        Serial.printf("Connected to %s, IP: %s\n", ssid.c_str(), WiFi.localIP().toString().c_str());
    } else {
        _server.send(200, "text/plain", "WiFi连接失败，请重试");
        WiFi.mode(WIFI_AP);
        WiFi.softAP(_apSsid, _apPassword);
    }
}

void EspWifiCfg::_handleNotFound() {
    _server.sendHeader("Location", "/", true);
    _server.send(302, "text/plain", "");
}
